﻿using System;
using System.Linq;
using Game.Foundation;
using Bruce.Net;
using System.Collections.Generic;

namespace Server.Game.Generic
{
    public abstract class AbsGameGroup
    {
        protected abstract int PlayerCountPerGroup
        { get; }

        private GameRoomServer _room;
        protected int _step;
        protected bool _completed;
        protected Player[] _playerArray;

        public int ID
        {
            get;
            private set;
        }

        public int RoomID
        {
            get
            {
                return this._room.ID;
            }
        }

        public GameRoomServer Room
        {
            get
            {
                return this._room;
            }
        }

        public Player this[int index]
        {
            get
            {
                return this._playerArray[index];
            }
            set
            {
                this._playerArray[index] = value;
            }
        }

        public event EventHandler<NewGameEventArgs> NewGameStarted;
        public event EventHandler GameCompleted;

        public AbsGameGroup(GameRoomServer room, int id)
        {
            this._room = room;
            this._completed = false;
            this.ID = id;
            this._playerArray = new Player[PlayerCountPerGroup];
        }

        /// <summary>
        /// 获取当前状态的二进制描述
        /// </summary>
        public byte[] GetBytes()
        {
            byte[] data = BitConverter.GetBytes(this._playerArray.Where(pp => pp != null).Count());
            foreach (Player proxy in this._playerArray.Where(pp => pp != null))
            {
                data = ArrayHelper.Join(data, BytesParser.StringToBytes(proxy.UserName));
                data = ArrayHelper.Join(data, new byte[] { proxy.SeatIndex });
                data = ArrayHelper.Join(data, new byte[] { (byte)proxy.Status });
            }

            return data;
        }

        public byte RegisterClient(Player proxy, byte index)
        {
            if (index >= PlayerCountPerGroup || index < 0 || proxy == null) return 9;
            if (this._playerArray[index] != null) return 2;
            if (proxy.Status == GameStatus.Gaming) return 3;


            if (proxy.Status != GameStatus.Absent)
            {
                proxy.Status = GameStatus.Absent;
            }
            proxy.Group = this;
            proxy.SeatIndex = index;
            this._playerArray[index] = proxy;
            proxy.Status = GameStatus.Unready;

            return 0;
        }

        public bool LogoutClient(Player proxy)
        {
            bool result = this._playerArray.Contains(proxy);
            if (result)
            {
                this._playerArray[Array.IndexOf(this._playerArray, proxy)] = null;
            }
            return result;
        }

        public void TryStart()
        {
            bool result = true;
            foreach (var item in this._playerArray)
            {
                result &= (item != null && item.Status == GameStatus.Ready);
                if (!result) return;
            }

            this.NewGame();
            this.ExchangeProxy();
        }

        private void NewGame()
        {
            this._completed = false;
            this._step = -1;
            this.InitializeNewGame();
            Array.ForEach(this._playerArray, p => p.Status = GameStatus.Gaming);

            if (this.NewGameStarted != null)
            {
                NewGameEventArgs e = new NewGameEventArgs();
                e.GroupID = this.ID;
                List<GameSeat> list = new List<GameSeat>();
                for (int i = 0; i < this._playerArray.Length; i++)
                {
                    list.Add(new GameSeat { SeatIndex = i, UserName = this._playerArray[i].UserName, });
                }
                e.SeatCollection = list;

                this.NewGameStarted(this, e);
            }
        }

        protected abstract void InitializeNewGame();
        public abstract void SynchronizeGame(Packet p);

        public void ExchangeProxy()
        {
            var player = this._playerArray[++this._step % PlayerCountPerGroup];
            Packet p = new Packet((int)PacketType.游戏换手操作通知包);
            p.WriteByte(player.SeatIndex);
            p.WriteString(player.UserName);
            foreach (var item in this._playerArray.Where(pp => pp != null))
            {
                item.SendMessage(p);
            }
        }

        protected void OnGameCompleted()
        {
            if (this.GameCompleted == null) return;

            this.GameCompleted(this, EventArgs.Empty);
        }
    }
}
